#include "bt_conn_mgr.h"
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <string.h>
#include <errno.h>
#include <zephyr/bluetooth/addr.h>

LOG_MODULE_REGISTER(bt_conn_mgr, LOG_LEVEL_DBG);

static struct bt_conn_mgr conn_mgr_list[CONN_MGR_MAX_CONN];
static struct k_mutex conn_mgr_mutex;

/* 全局 GATT 发现参数 */
static struct bt_gatt_discover_params discover_params;
static struct bt_gatt_discover_params char_discover_params;
static struct bt_gatt_discover_params desc_discover_params;

/* 用户传入的发现回调 */
static conn_discovery_cb_t user_discovery_cb = NULL;

/* 默认 notify 回调 */
static uint8_t default_notify_cb(struct bt_conn *conn,
                                 struct bt_gatt_subscribe_params *params,
                                 const void *data, uint16_t length)
{
    if (data && length > 0)
    {
        LOG_INF("Received notification, length: %u", length);
    }
    return BT_GATT_ITER_CONTINUE;
}

/* 初始化连接管理模块 */
void bt_conn_mgr_init(void)
{
    k_mutex_init(&conn_mgr_mutex);
    memset(conn_mgr_list, 0, sizeof(conn_mgr_list));
}

/* 添加连接管理对象，并保存远程设备地址 */
int bt_conn_mgr_add(struct bt_conn *conn)
{
    if (!conn)
    {
        return -EINVAL;
    }
    const bt_addr_le_t *addr = bt_conn_get_dst(conn);
    if (!addr)
    {
        return -EINVAL;
    }

    k_mutex_lock(&conn_mgr_mutex, K_FOREVER);
    for (int i = 0; i < CONN_MGR_MAX_CONN; i++)
    {
        if (conn_mgr_list[i].conn == NULL)
        {
            conn_mgr_list[i].conn = conn;
            conn_mgr_list[i].state = CONN_STATE_CONNECTED;
            memcpy(&conn_mgr_list[i].remote_addr, addr, sizeof(bt_addr_le_t));
            memset(&conn_mgr_list[i].subscribe_params, 0, sizeof(conn_mgr_list[i].subscribe_params));
            conn_mgr_list[i].start_handle = 0;
            conn_mgr_list[i].end_handle = 0;
            conn_mgr_list[i].write_handle = 0;
            conn_mgr_list[i].notify_handle = 0;
            conn_mgr_list[i].ccc_handle = 0;
            conn_mgr_list[i].discovered = false;
            conn_mgr_list[i].char_discovery_done = false;
            conn_mgr_list[i].desc_discovery_in_progress = false;
            k_mutex_unlock(&conn_mgr_mutex);
            char addr_str[BT_ADDR_LE_STR_LEN];
            bt_addr_le_to_str(&conn_mgr_list[i].remote_addr, addr_str, sizeof(addr_str));
            printk("Added connection mgr for conn, addr %s\n", addr_str);
            return 0;
        }
    }
    k_mutex_unlock(&conn_mgr_mutex);
    return -ENOMEM;
}

/* 移除连接管理对象 */
int bt_conn_mgr_remove(struct bt_conn *conn)
{
    if (!conn)
    {
        return -EINVAL;
    }
    k_mutex_lock(&conn_mgr_mutex, K_FOREVER);
    for (int i = 0; i < CONN_MGR_MAX_CONN; i++)
    {
        if (conn_mgr_list[i].conn == conn)
        {
            memset(&conn_mgr_list[i], 0, sizeof(conn_mgr_list[i]));
            k_mutex_unlock(&conn_mgr_mutex);
            printk("Removed connection mgr for conn %p", conn);
            return 0;
        }
    }
    k_mutex_unlock(&conn_mgr_mutex);
    return -ENOENT;
}

/* 根据 bt_conn 获取连接管理对象 */
struct bt_conn_mgr *bt_conn_mgr_get(struct bt_conn *conn)
{
    struct bt_conn_mgr *mgr = NULL;
    k_mutex_lock(&conn_mgr_mutex, K_FOREVER);
    for (int i = 0; i < CONN_MGR_MAX_CONN; i++)
    {
        if (conn_mgr_list[i].conn == conn)
        {
            mgr = &conn_mgr_list[i];
            break;
        }
    }
    k_mutex_unlock(&conn_mgr_mutex);
    return mgr;
}

/* 根据 MAC 地址字符串获取连接管理对象 */
struct bt_conn_mgr *bt_conn_mgr_get_by_mac(const char *mac_str)
{
    if (!mac_str)
    {
        return NULL;
    }
    bt_addr_le_t target;
    /* 使用 Zephyr 内部接口将字符串转换为 bt_addr_le_t；
     * 格式应为 "AA:BB:CC:DD:EE:FF" ，假设地址类型为 public  */
    int err = bt_addr_le_from_str(mac_str, "random", &target);
    if (err)
    {
        LOG_ERR("Failed to convert MAC string %s (err %d)", mac_str, err);
        return NULL;
    }

    struct bt_conn_mgr *mgr = NULL;
    k_mutex_lock(&conn_mgr_mutex, K_FOREVER);
    for (int i = 0; i < CONN_MGR_MAX_CONN; i++)
    {
        if (conn_mgr_list[i].conn)
        {
            /* 比较地址 */
            if (!bt_addr_le_cmp(&conn_mgr_list[i].remote_addr, &target))
            {
                mgr = &conn_mgr_list[i];
                break;
            }
        }
    }
    k_mutex_unlock(&conn_mgr_mutex);
    return mgr;
}

/* 集成的 GATT 发现回调，更新管理对象中的 GATT cache 字段 */
static uint8_t integrated_discover_cb(struct bt_conn *conn,
                                      const struct bt_gatt_attr *attr,
                                      struct bt_gatt_discover_params *params)
{
    struct bt_conn_mgr *mgr = bt_conn_mgr_get(conn);
    if (!mgr)
    {
        printk("Connection mgr not found for conn %p", conn);
        return BT_GATT_ITER_STOP;
    }

    k_mutex_lock(&conn_mgr_mutex, K_FOREVER);
    switch (params->type)
    {
        case BT_GATT_DISCOVER_PRIMARY:
            if (!attr)
            {
                LOG_ERR("Service not found");
                k_mutex_unlock(&conn_mgr_mutex);
                if (user_discovery_cb)
                {
                    user_discovery_cb(conn, -ENOENT);
                }
                return BT_GATT_ITER_STOP;
            }
            {
                struct bt_gatt_service_val *svc_val = (struct bt_gatt_service_val *)attr->user_data;
                mgr->start_handle = attr->handle;
                mgr->end_handle = svc_val->end_handle;
                LOG_INF("Found service: start 0x%04x, end 0x%04x", mgr->start_handle, mgr->end_handle);
                memset(&char_discover_params, 0, sizeof(char_discover_params));
                char_discover_params.uuid = NULL; /* 查找所有特征 */
                char_discover_params.start_handle = mgr->start_handle;
                char_discover_params.end_handle = mgr->end_handle;
                char_discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
                char_discover_params.func = integrated_discover_cb;
            }
            k_mutex_unlock(&conn_mgr_mutex);
            {
                int err = bt_gatt_discover(conn, &char_discover_params);
                if (err)
                {
                    LOG_ERR("Characteristic discovery failed, err %d", err);
                    if (user_discovery_cb)
                    {
                        user_discovery_cb(conn, err);
                    }
                    return BT_GATT_ITER_STOP;
                }
            }
            return BT_GATT_ITER_STOP;

        case BT_GATT_DISCOVER_CHARACTERISTIC:
            if (!attr)
            {
                mgr->char_discovery_done = true;
                LOG_INF("Characteristic discovery complete");
                if (!mgr->desc_discovery_in_progress)
                {
                    mgr->discovered = true;
                    k_mutex_unlock(&conn_mgr_mutex);
                    if (user_discovery_cb)
                    {
                        user_discovery_cb(conn, 0);
                    }
                }
                else
                {
                    k_mutex_unlock(&conn_mgr_mutex);
                }
                return BT_GATT_ITER_STOP;
            }
            {
                struct bt_gatt_chrc *chrc = (struct bt_gatt_chrc *)attr->user_data;
                LOG_INF("Found characteristic: handle 0x%04x, properties 0x%02x",
                        chrc->value_handle, chrc->properties);
                if (((chrc->properties & BT_GATT_CHRC_WRITE) ||
                     (chrc->properties & BT_GATT_CHRC_WRITE_WITHOUT_RESP)) &&
                    (mgr->write_handle == 0))
                {
                    mgr->write_handle = chrc->value_handle;
                    LOG_INF("Write char handle: 0x%04x", mgr->write_handle);
                }
                if ((chrc->properties & BT_GATT_CHRC_NOTIFY) && (mgr->notify_handle == 0))
                {
                    mgr->notify_handle = chrc->value_handle;
                    LOG_INF("Notify char handle: 0x%04x", mgr->notify_handle);
                    if (mgr->ccc_handle == 0)
                    {
                        mgr->desc_discovery_in_progress = true;
                        memset(&desc_discover_params, 0, sizeof(desc_discover_params));
                        desc_discover_params.uuid = BT_UUID_GATT_CCC;
                        desc_discover_params.start_handle = chrc->value_handle + 1;
                        desc_discover_params.end_handle = mgr->end_handle;
                        desc_discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
                        desc_discover_params.func = integrated_discover_cb;
                        LOG_INF("Start CCC descriptor discovery");
                        k_mutex_unlock(&conn_mgr_mutex);
                        int err = bt_gatt_discover(conn, &desc_discover_params);
                        if (err)
                        {
                            LOG_ERR("Descriptor discovery failed, err %d", err);
                            if (user_discovery_cb)
                            {
                                user_discovery_cb(conn, err);
                            }
                            return BT_GATT_ITER_STOP;
                        }
                        return BT_GATT_ITER_STOP;
                    }
                }
            }
            k_mutex_unlock(&conn_mgr_mutex);
            return BT_GATT_ITER_CONTINUE;

        case BT_GATT_DISCOVER_DESCRIPTOR:
            if (attr)
            {
                if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CCC))
                {
                    mgr->ccc_handle = attr->handle;
                    LOG_INF("Found CCC descriptor: handle 0x%04x", mgr->ccc_handle);
                    k_mutex_unlock(&conn_mgr_mutex);
                    /* 无论如何都调用用户回调一次 */
                    if (user_discovery_cb)
                    {
                        user_discovery_cb(conn, 0);
                    }
                    return BT_GATT_ITER_STOP;
                }
                k_mutex_unlock(&conn_mgr_mutex);
                return BT_GATT_ITER_CONTINUE;
            }
            else
            {
                mgr->desc_discovery_in_progress = false;
                LOG_INF("Descriptor discovery complete");
                if (mgr->char_discovery_done && !mgr->discovered)
                {
                    mgr->discovered = true;
                    k_mutex_unlock(&conn_mgr_mutex);
                    if (user_discovery_cb)
                    {
                        user_discovery_cb(conn, 0);
                    }
                }
                else
                {
                    k_mutex_unlock(&conn_mgr_mutex);
                }
                return BT_GATT_ITER_STOP;
            }
        default:
            break;
    }
    k_mutex_unlock(&conn_mgr_mutex);
    return BT_GATT_ITER_STOP;
}

/* 发起 GATT 服务发现，并更新连接状态 */
int bt_conn_mgr_discover(struct bt_conn *conn, const struct bt_uuid *svc_uuid,
                         conn_discovery_cb_t cb)
{
    if (!conn || !svc_uuid || !cb)
    {
        return -EINVAL;
    }
    user_discovery_cb = cb;
    struct bt_conn_mgr *mgr = bt_conn_mgr_get(conn);
    if (!mgr)
    {
        return -ENOMEM;
    }
    k_mutex_lock(&conn_mgr_mutex, K_FOREVER);
    mgr->start_handle = 0;
    mgr->end_handle = 0;
    mgr->write_handle = 0;
    mgr->notify_handle = 0;
    mgr->ccc_handle = 0;
    mgr->discovered = false;
    mgr->char_discovery_done = false;
    mgr->desc_discovery_in_progress = false;
    memset(&mgr->subscribe_params, 0, sizeof(mgr->subscribe_params));
    memset(&mgr->write_params, 0, sizeof(mgr->write_params));
    k_mutex_unlock(&conn_mgr_mutex);

    memset(&discover_params, 0, sizeof(discover_params));
    discover_params.uuid = svc_uuid;
    discover_params.func = integrated_discover_cb;
    discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
    discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
    discover_params.type = BT_GATT_DISCOVER_PRIMARY;

    int err = bt_gatt_discover(conn, &discover_params);
    if (err)
    {
        LOG_ERR("Primary service discovery failed, err %d", err);
        return err;
    }
    k_mutex_lock(&conn_mgr_mutex, K_FOREVER);
    mgr->state = CONN_STATE_DISCOVERING;
    k_mutex_unlock(&conn_mgr_mutex);
    LOG_INF("GATT discovery initiated");
    return 0;
}

/* 通过指定连接发送数据（基于发现到的写特征） */
int bt_conn_mgr_send_data(struct bt_conn *conn, const uint8_t *data, uint16_t len)
{
    if (!conn || !data || len == 0)
    {
        return -EINVAL;
    }
    struct bt_conn_mgr *mgr = bt_conn_mgr_get(conn);
    if (!mgr || mgr->write_handle == 0)
    {
        LOG_ERR("No valid write characteristic found");
        return -ENODATA;
    }
    int err = bt_gatt_write_without_response(conn, mgr->write_handle, data, len, false);
    if (err)
    {
        LOG_ERR("Failed to send data, err %d", err);
        return err;
    }
    LOG_INF("Data sent successfully");
    return 0;
}

/* 使能或禁用 notify（基于发现到的 notify 特征及 CCC 描述符） */
int bt_conn_mgr_notify_enable(struct bt_conn *conn, bool enable, bt_gatt_notify_func_t notify_cb)
{
    if (!conn)
    {
        return -EINVAL;
    }
    struct bt_conn_mgr *mgr = bt_conn_mgr_get(conn);
    if (!mgr || mgr->notify_handle == 0)
    {
        LOG_ERR("No valid notify characteristic found");
        return -ENODATA;
    }
    k_mutex_lock(&conn_mgr_mutex, K_FOREVER);
    if (mgr->subscribe_params.value_handle != 0)
    {
        LOG_INF("Notify already subscribed");
        k_mutex_unlock(&conn_mgr_mutex);
        return 0;
    }
    memset(&mgr->subscribe_params, 0, sizeof(mgr->subscribe_params));
    mgr->subscribe_params.value_handle = mgr->notify_handle;
    mgr->subscribe_params.ccc_handle = (mgr->ccc_handle != 0) ? mgr->ccc_handle : 0;
    mgr->subscribe_params.value = enable ? BT_GATT_CCC_NOTIFY : 0;
    mgr->subscribe_params.notify = notify_cb ? notify_cb : default_notify_cb;
    k_mutex_unlock(&conn_mgr_mutex);

    int err = bt_gatt_subscribe(conn, &mgr->subscribe_params);
    if (err && err != -EALREADY)
    {
        LOG_ERR("Failed to enable notify, err %d", err);
        return err;
    }
    LOG_INF("Notify subscription successful");
    return err;
}

/* 重置指定连接的 GATT cache 数据（集成在连接管理对象中） */
void bt_conn_mgr_reset(struct bt_conn *conn)
{
    if (!conn)
    {
        return;
    }
    k_mutex_lock(&conn_mgr_mutex, K_FOREVER);
    struct bt_conn_mgr *mgr = bt_conn_mgr_get(conn);
    if (mgr)
    {
        printk("Resetting connection mgr for conn %p", conn);
        mgr->start_handle = 0;
        mgr->end_handle = 0;
        mgr->write_handle = 0;
        mgr->notify_handle = 0;
        mgr->ccc_handle = 0;
        mgr->discovered = false;
        mgr->char_discovery_done = false;
        mgr->desc_discovery_in_progress = false;
        memset(&mgr->subscribe_params, 0, sizeof(mgr->subscribe_params));
        memset(&mgr->write_params, 0, sizeof(mgr->write_params));
    }
    k_mutex_unlock(&conn_mgr_mutex);
}

/* 发起 GATT 服务发现：先通过 MAC 地址查找对应连接管理对象 */
int bt_conn_mgr_discover_by_mac(const char *mac_str, const struct bt_uuid *svc_uuid,
                                conn_discovery_cb_t cb)
{
    struct bt_conn_mgr *mgr = bt_conn_mgr_get_by_mac(mac_str);
    if (!mgr || !mgr->conn)
    {
        LOG_ERR("No connection found for MAC %s", mac_str);
        return -ENOENT;
    }
    return bt_conn_mgr_discover(mgr->conn, svc_uuid, cb);
}

/* 发送数据包装接口 */
int bt_conn_mgr_send_data_by_mac(const char *mac_str, const uint8_t *data, uint16_t len)
{
    struct bt_conn_mgr *mgr = bt_conn_mgr_get_by_mac(mac_str);
    if (!mgr || !mgr->conn)
    {
        LOG_ERR("No connection found for MAC %s", mac_str);
        return -ENOENT;
    }
    return bt_conn_mgr_send_data(mgr->conn, data, len);
}

/* notify 使能包装接口 */
int bt_conn_mgr_notify_enable_by_mac(const char *mac_str, bool enable, bt_gatt_notify_func_t notify_cb)
{
    struct bt_conn_mgr *mgr = bt_conn_mgr_get_by_mac(mac_str);
    if (!mgr || !mgr->conn)
    {
        LOG_ERR("No connection found for MAC %s", mac_str);
        return -ENOENT;
    }
    return bt_conn_mgr_notify_enable(mgr->conn, enable, notify_cb);
}
